purpose of notebook

(/) describe & visualize single variables (univariate) (-) gather interesting observations for further investigation (-) gather possible new features for extraction

todos: (-) …

information
https://www.kaggle.com/sobhanmoosavi/us-weather-events https://smoosavi.org/datasets/lstw
Moosavi, Sobhan, Mohammad Hossein Samavatian, Arnab Nandi, Srinivasan Parthasarathy, and Rajiv Ramnath. “Short and Long-term Pattern Discovery Over Large-Scale Geo-Spatiotemporal Data.” In Proceedings of the 25th ACM SIGKDD International Conference on Knowledge Discovery & Data Mining, ACM, 2019.
Weather event is a spatiotemporal entity, where such an entity is associated with location and time. Following is the description of available weather event types:
Severe-Cold: The case of having extremely low temperature, with temperature below -23.7 degrees of Celsius. Fog: The case where there is low visibility condition as a result of fog or haze. Hail: The case of having solid precipitation including ice pellets and hail. Rain: The case of having rain, ranging from light to heavy. Snow: The case of having snow, ranging from light to heavy. Storm: The extremely windy condition, where the wind speed is at least 60 km/h. Other Precipitation: Any other type of precipitation which cannot be assigned to previously described event types.
The weather data is provided in terms of a CSV file with the following attributes: Attribute Description Nullable 1 EventId This is the identifier of a record No 2 Type The type of an event; examples are rain and snow. No 3 Severity The severity of an event, wherever applicable. Yes 4 StartTime (UTC) The start time of an event in UTC time zone. No 5 EndTime (UTC) The end time of an event in UTC time zone. No 6 TimeZone The US-based timezone based on the location of an event No (eastern, central, mountain, and pacific). 7 LocationLat The latitude in GPS coordinate. Yes 8 LocationLng The longitude in GPS coordinate. Yes 9 AirportCode The airport station that a weather event is reported from. Yes 10 City The city in address record. Yes 11 County The county in address record. Yes 12 State The state in address record. Yes 13 ZipCode The zipcode in address record. Yes

insights

  1. Seattle: events come in waves within the year (peak in Nov, low in Jul) but stable across years,
  2. Houston: events seem stable, spontaneous less in Jul and Nov,
  3. York: stable but jump to more in 2018, stable across week and year
  4. Los Angeles: kind of stable but spike around 2017 and increase 2019 and 2020, over week spikes on monday and thursday, little wave with peak in Jan and low an Jun, distribution over hours shows significant peak at 15:00
  5. all: distribution over month days always low at first and last two, distribution over minutes have (different, but all at end of hour) enormous peaks for each city
  6. since human judgment seems to be involved, the duration has peaks at the full hours, you even can see the dips in the poisson like distribution
  7. duration stats: Seattle median 60 min, q3 120 min; New York median 47 min q3 72 min; Los Angeles median 60 min q3 120 min, Houston median 60 min q3 98 min; Los Angeles and Seattle seem similar in distribution
stories

(!) compare 4 big cities which are all close to the coast but vary in significantly in longitude and latitude

load packages
overview
head(weather)
summary(weather)
   EventId                     Type          Severity      StartTime                      EndTime                          TimeZone     LocationLat     LocationLng     
 Length:12226       Cold         : 365   Heavy   : 439   Min.   :2016-01-01 08:47:00   Min.   :2016-01-01 09:47:00   US/Central:2900   Min.   :29.98   Min.   :-122.31  
 Class :character   Fog          :2920   Light   :6792   1st Qu.:2017-04-08 08:59:45   1st Qu.:2017-04-08 11:06:30   US/Eastern:3656   1st Qu.:34.02   1st Qu.:-122.31  
 Mode  :character   Hail         :   6   Moderate:3428   Median :2018-09-27 02:42:30   Median :2018-09-27 03:02:30   US/Pacific:5670   Median :40.78   Median : -95.36  
                    Precipitation: 139   Other   :   6   Mean   :2018-08-09 22:18:52   Mean   :2018-08-09 23:49:14                     Mean   :38.70   Mean   :-100.68  
                    Rain         :8296   Severe  :1422   3rd Qu.:2019-11-24 10:37:30   3rd Qu.:2019-11-24 12:37:30                     3rd Qu.:47.44   3rd Qu.: -73.97  
                    Snow         : 494   UNK     : 139   Max.   :2020-12-31 23:22:00   Max.   :2020-12-31 23:53:00                     Max.   :47.44   Max.   : -73.97  
                    Storm        :   6                                                                                                                                  
          City        Duration       
 Houston    :2900   Length:12226     
 Los Angeles:2378   Class :difftime  
 New York   :3656   Mode  :numeric   
 Seattle    :3292                    
                                     
                                     
                                     
univariate StartTime

StartTime and EndTime look almost the same, thus we only look at StartTime for univariate exploration Seattle: events come in waves within the year (peak in Nov, low in Jul) but stable across years, Houston: events seem stable, spontaneous less in Jul and Nov, New York: stable but jump to more in 2018, stable across week and year Los Angeles: kind of stable but spike around 2017 and increase 2019 and 2020, over week spikes on monday and thursday, little wave with peak in Jan and low an Jun, distribution over hours shows significant peak at 15:00 all: distribution over month days always low at first and last two, distribution over minutes have (different, but all at end of hour) enormous peaks for each city

startTime_plot <- weather %>%
  ggplot(aes(x = StartTime, y = City, col = fct_infreq(City))) +
    geom_jitter(alpha = 0.2, size = 0.5) +
    theme_minimal() +
    ggtitle("StartTime of the events")

ggplotly(startTime_plot)
# https://r4ds.had.co.nz/dates-and-times.html
# Note that when you use date-times in a numeric context (like in a histogram), 1 means 1 second, so a binwidth of 86400 means one day. For dates, 1 means 1 day.
startTime_freqplot <- weather %>%
  ggplot(aes(x = StartTime, col = City)) +
    geom_freqpoly(bins = 30) + # binwidth = 86400 seconds = 1 day, 600 s = 10 minutes
    theme_minimal() +
    ggtitle("frequency plot for StartTime") +
    facet_grid(rows = vars(City))

ggplotly(startTime_freqplot)
startTime_barplot_wday <- weather %>%
  mutate(wday = wday(StartTime, label = TRUE)) %>%
  ggplot(aes(x = wday, fill = City)) +
    geom_bar() +
    facet_grid(rows = vars(City)) +
    theme_minimal() +
    ggtitle("distribution over week days")
  
ggplotly(startTime_barplot_wday)
startTime_barplot_year <- weather %>%
  mutate(year = year(StartTime)) %>%
  ggplot(aes(x = year, fill = City)) +
    geom_bar() +
    facet_grid(rows = vars(City)) +
    theme_minimal() +
    ggtitle("distribution over years")
  
ggplotly(startTime_barplot_year)
startTime_barplot_month <- weather %>%
  mutate(month = month(StartTime, label = TRUE)) %>%
  ggplot(aes(x = month, fill = City)) +
    geom_bar() +
    facet_grid(rows = vars(City)) +
    theme_minimal() +
    ggtitle("distribution over months")
  
ggplotly(startTime_barplot_month)
startTime_barplot_yday <- weather %>%
  mutate(yday = yday(StartTime)) %>%
  ggplot(aes(x = yday, fill = City)) +
    geom_bar() +
    facet_grid(rows = vars(City)) +
    theme_minimal() +
    ggtitle("distribution over days of year")
  
ggplotly(startTime_barplot_yday)
startTime_barplot_mday <- weather %>%
  mutate(mday = mday(StartTime)) %>%
  ggplot(aes(x = mday, fill = City)) +
    geom_bar() +
    facet_grid(rows = vars(City)) +
    theme_minimal() +
    ggtitle("distribution over days of month")
  
ggplotly(startTime_barplot_mday)
startTime_barplot_hour <- weather %>%
  mutate(hour = hour(StartTime)) %>%
  ggplot(aes(x = hour, fill = City)) +
    geom_bar() +
    facet_grid(rows = vars(City)) +
    theme_minimal() +
    ggtitle("distribution over hours")
  
ggplotly(startTime_barplot_hour)
startTime_barplot_minute <- weather %>%
  mutate(minute = minute(StartTime)) %>%
  ggplot(aes(x = minute, fill = City)) +
    geom_bar() +
    facet_grid(rows = vars(City)) +
    theme_minimal() +
    ggtitle("distribution over minutes")
  
ggplotly(startTime_barplot_minute)
# Setting larger components of a date to a constant is a powerful technique that allows you to explore patterns in the smaller components.
startTime_count <- weather %>%
  mutate(start_hour = update(StartTime, mday = 1)) %>%
  ggplot(aes(x = start_hour, col = City)) +
    geom_freqpoly() +
    facet_grid(rows = vars(City)) +
    theme_minimal() +
    ggtitle("not seeing the use here, but wanted to check out")

ggplotly(startTime_count)
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
univariate Duration

since human judgment seems to be involved, the duration has peaks at the full hours, you even can see the dips in the poisson like distribution duration stats: Seattle median 60 min, q3 120 min; New York median 47 min q3 72 min; Los Angeles median 60 min q3 120 min, Houston median 60 min q3 98 min; Los Angeles and Seattle seem similar in distribution

duration_histplot_all <- weather %>%
  ggplot(aes(x = Duration, fill = fct_infreq(City))) +
    geom_histogram(binwidth = 1) +
    theme_minimal() +
    ggtitle("Duration of the events")

ggplotly(duration_histplot_all)
Don't know how to automatically pick scale for object of type difftime. Defaulting to continuous.
duration_histplot <- weather %>%
  ggplot(aes(x = Duration, fill = fct_infreq(City))) +
    geom_histogram(binwidth = 30) +
    theme_minimal() +
    ggtitle("Duration of the events") +
    facet_grid(rows = vars(City))

ggplotly(duration_histplot)
Don't know how to automatically pick scale for object of type difftime. Defaulting to continuous.
duration_boxplot <- weather %>%
  ggplot(aes(y = as.numeric(Duration), x = City, col = fct_infreq(City))) +
    geom_boxplot() +
    theme_minimal() +
    coord_flip() +
    ggtitle("Duration of the events")

ggplotly(duration_boxplot)
duration_boxplot <- weather %>%
  ggplot(aes(x = as.numeric(Duration), y = City, col = fct_infreq(City))) +
    geom_jitter(alpha = 0.2, size = 0.5) +
    theme_minimal() +
    ggtitle("Duration of the events")

ggplotly(duration_boxplot)
library(dlookr)

weather %>% 
  mutate(Duration = as.numeric(Duration)) %>%
  plot_normality(Duration)

LS0tDQp0aXRsZTogImRlc2NyaWJlIGFuZCB2aXN1YWxpemUgb2YgVVMgd2VhdGhlciBldmVudCBkYXRhIg0Kc3VidGl0bGU6ICJjaXR5IHNlbGVjdGlvbiAtIHVuaXZhcmlhdGUgZm9yIHRpbWUgdmFyaWFibGVzIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KLS0tDQpwdXJwb3NlIG9mIG5vdGVib29rDQotLS0NCg0KICAoLykgZGVzY3JpYmUgJiB2aXN1YWxpemUgc2luZ2xlIHZhcmlhYmxlcyAodW5pdmFyaWF0ZSkNCiAgKC0pIGdhdGhlciBpbnRlcmVzdGluZyBvYnNlcnZhdGlvbnMgZm9yIGZ1cnRoZXIgaW52ZXN0aWdhdGlvbg0KICAoLSkgZ2F0aGVyIHBvc3NpYmxlIG5ldyBmZWF0dXJlcyBmb3IgZXh0cmFjdGlvbg0KICANCnRvZG9zOg0KICAoLSkgLi4uDQoNCi0tLQ0KaW5mb3JtYXRpb24NCi0tLQ0KaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9zb2JoYW5tb29zYXZpL3VzLXdlYXRoZXItZXZlbnRzDQpodHRwczovL3Ntb29zYXZpLm9yZy9kYXRhc2V0cy9sc3R3DQoNCk1vb3NhdmksIFNvYmhhbiwgTW9oYW1tYWQgSG9zc2VpbiBTYW1hdmF0aWFuLCBBcm5hYiBOYW5kaSwgU3Jpbml2YXNhbiBQYXJ0aGFzYXJhdGh5LCBhbmQgUmFqaXYgUmFtbmF0aC4g4oCcU2hvcnQgYW5kIExvbmctdGVybSBQYXR0ZXJuIERpc2NvdmVyeSBPdmVyIExhcmdlLVNjYWxlIEdlby1TcGF0aW90ZW1wb3JhbCBEYXRhLuKAnSBJbiBQcm9jZWVkaW5ncyBvZiB0aGUgMjV0aCBBQ00gU0lHS0REIEludGVybmF0aW9uYWwgQ29uZmVyZW5jZSBvbiBLbm93bGVkZ2UgRGlzY292ZXJ5ICYgRGF0YSBNaW5pbmcsIEFDTSwgMjAxOS4NCg0KV2VhdGhlciBldmVudCBpcyBhIHNwYXRpb3RlbXBvcmFsIGVudGl0eSwgd2hlcmUgc3VjaCBhbiBlbnRpdHkgaXMgYXNzb2NpYXRlZCB3aXRoIGxvY2F0aW9uIGFuZCB0aW1lLiBGb2xsb3dpbmcgaXMgdGhlIGRlc2NyaXB0aW9uIG9mIGF2YWlsYWJsZSB3ZWF0aGVyIGV2ZW50IHR5cGVzOg0KDQogICAgU2V2ZXJlLUNvbGQ6IFRoZSBjYXNlIG9mIGhhdmluZyBleHRyZW1lbHkgbG93IHRlbXBlcmF0dXJlLCB3aXRoIHRlbXBlcmF0dXJlIGJlbG93IC0yMy43IGRlZ3JlZXMgb2YgQ2Vsc2l1cy4NCiAgICBGb2c6IFRoZSBjYXNlIHdoZXJlIHRoZXJlIGlzIGxvdyB2aXNpYmlsaXR5IGNvbmRpdGlvbiBhcyBhIHJlc3VsdCBvZiBmb2cgb3IgaGF6ZS4NCiAgICBIYWlsOiBUaGUgY2FzZSBvZiBoYXZpbmcgc29saWQgcHJlY2lwaXRhdGlvbiBpbmNsdWRpbmcgaWNlIHBlbGxldHMgYW5kIGhhaWwuDQogICAgUmFpbjogVGhlIGNhc2Ugb2YgaGF2aW5nIHJhaW4sIHJhbmdpbmcgZnJvbSBsaWdodCB0byBoZWF2eS4NCiAgICBTbm93OiBUaGUgY2FzZSBvZiBoYXZpbmcgc25vdywgcmFuZ2luZyBmcm9tIGxpZ2h0IHRvIGhlYXZ5Lg0KICAgIFN0b3JtOiBUaGUgZXh0cmVtZWx5IHdpbmR5IGNvbmRpdGlvbiwgd2hlcmUgdGhlIHdpbmQgc3BlZWQgaXMgYXQgbGVhc3QgNjAga20vaC4NCiAgICBPdGhlciBQcmVjaXBpdGF0aW9uOiBBbnkgb3RoZXIgdHlwZSBvZiBwcmVjaXBpdGF0aW9uIHdoaWNoIGNhbm5vdCBiZSBhc3NpZ25lZCB0byBwcmV2aW91c2x5IGRlc2NyaWJlZCBldmVudCB0eXBlcy4NCg0KVGhlIHdlYXRoZXIgZGF0YSBpcyBwcm92aWRlZCBpbiB0ZXJtcyBvZiBhIENTViBmaWxlIHdpdGggdGhlIGZvbGxvd2luZyBhdHRyaWJ1dGVzOg0KICAgICAgQXR0cmlidXRlCSAgICAgICAgRGVzY3JpcHRpb24JICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTnVsbGFibGUNCjEJICAgIEV2ZW50SWQJICAgICAgICAgIFRoaXMgaXMgdGhlIGlkZW50aWZpZXIgb2YgYSByZWNvcmQJICAgICAgICAgICAgICAgICAgICAgICAgTm8NCjIgICAJVHlwZQkgICAgICAgICAgICBUaGUgdHlwZSBvZiBhbiBldmVudDsgZXhhbXBsZXMgYXJlIHJhaW4gYW5kIHNub3cuCSAgICAgICAgICBObw0KMwkgICAgU2V2ZXJpdHkJICAgICAgICBUaGUgc2V2ZXJpdHkgb2YgYW4gZXZlbnQsIHdoZXJldmVyIGFwcGxpY2FibGUuICAgICAgICAJICAgIFllcw0KNAkgICAgU3RhcnRUaW1lIChVVEMpCSAgVGhlIHN0YXJ0IHRpbWUgb2YgYW4gZXZlbnQgaW4gVVRDIHRpbWUgem9uZS4gICAgICAgICAgCSAgICBObw0KNQkgICAgRW5kVGltZSAoVVRDKQkgICAgVGhlIGVuZCB0aW1lIG9mIGFuIGV2ZW50IGluIFVUQyB0aW1lIHpvbmUuCSAgICAgICAgICAgICAgICBObw0KNgkgICAgVGltZVpvbmUJICAgICAgICBUaGUgVVMtYmFzZWQgdGltZXpvbmUgYmFzZWQgb24gdGhlIGxvY2F0aW9uIG9mIGFuIGV2ZW50ICAgICBObw0KICAgICAgICAgICAgICAgICAgICAgICAgKGVhc3Rlcm4sIGNlbnRyYWwsIG1vdW50YWluLCBhbmQgcGFjaWZpYykuCQ0KNwkgICAgTG9jYXRpb25MYXQJICAgICAgVGhlIGxhdGl0dWRlIGluIEdQUyBjb29yZGluYXRlLgkgICAgICAgICAgICAgICAgICAgICAgICAgICAgWWVzDQo4ICAgCUxvY2F0aW9uTG5nCSAgICAgIFRoZSBsb25naXR1ZGUgaW4gR1BTIGNvb3JkaW5hdGUuCSAgICAgICAgICAgICAgICAgICAgICAgICAgWWVzDQo5CSAgICBBaXJwb3J0Q29kZQkgICAgICBUaGUgYWlycG9ydCBzdGF0aW9uIHRoYXQgYSB3ZWF0aGVyIGV2ZW50IGlzIHJlcG9ydGVkIGZyb20uCVllcw0KMTAJICBDaXR5CSAgICAgICAgICAgIFRoZSBjaXR5IGluIGFkZHJlc3MgcmVjb3JkLgkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFllcw0KMTEJICBDb3VudHkJICAgICAgICAgIFRoZSBjb3VudHkgaW4gYWRkcmVzcyByZWNvcmQuCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFllcw0KMTIJICBTdGF0ZQkgICAgICAgICAgICBUaGUgc3RhdGUgaW4gYWRkcmVzcyByZWNvcmQuCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFllcw0KMTMJICBaaXBDb2RlCSAgICAgICAgICBUaGUgemlwY29kZSBpbiBhZGRyZXNzIHJlY29yZC4JICAgICAgICAgICAgICAgICAgICAgICAgICAgIFllcw0KDQotLS0NCmluc2lnaHRzIA0KLS0tDQogIA0KICAoaSkgU2VhdHRsZTogZXZlbnRzIGNvbWUgaW4gd2F2ZXMgd2l0aGluIHRoZSB5ZWFyIChwZWFrIGluIE5vdiwgbG93IGluIEp1bCkgYnV0IHN0YWJsZSBhY3Jvc3MgeWVhcnMsIA0KICAoaSkgSG91c3RvbjogZXZlbnRzIHNlZW0gc3RhYmxlLCBzcG9udGFuZW91cyBsZXNzIGluIEp1bCBhbmQgTm92LCANCiAgKGkpIFlvcms6IHN0YWJsZSBidXQganVtcCB0byBtb3JlIGluIDIwMTgsIHN0YWJsZSBhY3Jvc3Mgd2VlayBhbmQgeWVhcg0KICAoaSkgTG9zIEFuZ2VsZXM6IGtpbmQgb2Ygc3RhYmxlIGJ1dCBzcGlrZSBhcm91bmQgMjAxNyBhbmQgaW5jcmVhc2UgMjAxOSBhbmQgMjAyMCwgb3ZlciB3ZWVrIHNwaWtlcyBvbiBtb25kYXkgYW5kIHRodXJzZGF5LCBsaXR0bGUgd2F2ZSB3aXRoIHBlYWsgaW4gSmFuIGFuZCBsb3cgYW4gSnVuLCANCiAgICAgIGRpc3RyaWJ1dGlvbiBvdmVyIGhvdXJzIHNob3dzIHNpZ25pZmljYW50IHBlYWsgYXQgMTU6MDANCiAgKGkpIGFsbDogZGlzdHJpYnV0aW9uIG92ZXIgbW9udGggZGF5cyBhbHdheXMgbG93IGF0IGZpcnN0IGFuZCBsYXN0IHR3bywgZGlzdHJpYnV0aW9uIG92ZXIgbWludXRlcyBoYXZlIChkaWZmZXJlbnQsIGJ1dCBhbGwgYXQgZW5kIG9mIGhvdXIpIGVub3Jtb3VzIHBlYWtzIGZvciBlYWNoIGNpdHkNCiAgKGkpIHNpbmNlIGh1bWFuIGp1ZGdtZW50IHNlZW1zIHRvIGJlIGludm9sdmVkLCB0aGUgZHVyYXRpb24gaGFzIHBlYWtzIGF0IHRoZSBmdWxsIGhvdXJzLCB5b3UgZXZlbiBjYW4gc2VlIHRoZSBkaXBzIGluIHRoZSBwb2lzc29uIGxpa2UgZGlzdHJpYnV0aW9uDQogIChpKSBkdXJhdGlvbiBzdGF0czogU2VhdHRsZSBtZWRpYW4gNjAgbWluLCBxMyAxMjAgbWluOyBOZXcgWW9yayBtZWRpYW4gNDcgbWluIHEzIDcyIG1pbjsgTG9zIEFuZ2VsZXMgbWVkaWFuIDYwIG1pbiBxMyAxMjAgbWluLCBIb3VzdG9uIG1lZGlhbiA2MCBtaW4gcTMgOTggbWluOyANCiAgICAgIExvcyBBbmdlbGVzIGFuZCBTZWF0dGxlIHNlZW0gc2ltaWxhciBpbiBkaXN0cmlidXRpb24NCg0KLS0tDQpzdG9yaWVzDQotLS0NCg0KICAoISkgY29tcGFyZSA0IGJpZyBjaXRpZXMgd2hpY2ggYXJlIGFsbCBjbG9zZSB0byB0aGUgY29hc3QgYnV0IHZhcnkgaW4gc2lnbmlmaWNhbnRseSBpbiBsb25naXR1ZGUgYW5kIGxhdGl0dWRlDQoNCi0tLQ0KbG9hZCBwYWNrYWdlcw0KLS0tDQpgYGB7ciBsb2FkIHBhY2thZ2VzLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpICMgdGlkeSBkYXRhIGZyYW1lDQpsaWJyYXJ5KGdndGhlbWVzKSAjIGZvciBleHRyYSBwbG90IHRoZW1lcw0KbGlicmFyeShwbG90bHkpICMgbWFrZSBnZ3Bsb3RzIGludGVyYWN0aXZlDQpsaWJyYXJ5KGx1YnJpZGF0ZSkgIyBmdW5jdGlvbnMgdG8gd29yayB3aXRoIGRhdGUtdGltZXMgYW5kIHRpbWUtc3BhbnMNCmxpYnJhcnkoY29ycnBsb3QpICMgY29ycmVsYXRpb24gcGxvdHMNCmBgYA0KDQotLS0NCm92ZXJ2aWV3DQotLS0NCmBgYHtyfQ0KaGVhZCh3ZWF0aGVyKQ0KYGBgDQpgYGB7cn0NCnN1bW1hcnkod2VhdGhlcikNCmBgYA0KDQotLS0NCnVuaXZhcmlhdGUgU3RhcnRUaW1lDQotLS0NClN0YXJ0VGltZSBhbmQgRW5kVGltZSBsb29rIGFsbW9zdCB0aGUgc2FtZSwgdGh1cyB3ZSBvbmx5IGxvb2sgYXQgU3RhcnRUaW1lIGZvciB1bml2YXJpYXRlIGV4cGxvcmF0aW9uDQpTZWF0dGxlOiBldmVudHMgY29tZSBpbiB3YXZlcyB3aXRoaW4gdGhlIHllYXIgKHBlYWsgaW4gTm92LCBsb3cgaW4gSnVsKSBidXQgc3RhYmxlIGFjcm9zcyB5ZWFycywgDQpIb3VzdG9uOiBldmVudHMgc2VlbSBzdGFibGUsIHNwb250YW5lb3VzIGxlc3MgaW4gSnVsIGFuZCBOb3YsIA0KTmV3IFlvcms6IHN0YWJsZSBidXQganVtcCB0byBtb3JlIGluIDIwMTgsIHN0YWJsZSBhY3Jvc3Mgd2VlayBhbmQgeWVhcg0KTG9zIEFuZ2VsZXM6IGtpbmQgb2Ygc3RhYmxlIGJ1dCBzcGlrZSBhcm91bmQgMjAxNyBhbmQgaW5jcmVhc2UgMjAxOSBhbmQgMjAyMCwgb3ZlciB3ZWVrIHNwaWtlcyBvbiBtb25kYXkgYW5kIHRodXJzZGF5LCBsaXR0bGUgd2F2ZSB3aXRoIHBlYWsgaW4gSmFuIGFuZCBsb3cgYW4gSnVuLCBkaXN0cmlidXRpb24gb3ZlciBob3VycyBzaG93cyBzaWduaWZpY2FudCBwZWFrIGF0IDE1OjAwDQphbGw6IGRpc3RyaWJ1dGlvbiBvdmVyIG1vbnRoIGRheXMgYWx3YXlzIGxvdyBhdCBmaXJzdCBhbmQgbGFzdCB0d28sIGRpc3RyaWJ1dGlvbiBvdmVyIG1pbnV0ZXMgaGF2ZSAoZGlmZmVyZW50LCBidXQgYWxsIGF0IGVuZCBvZiBob3VyKSBlbm9ybW91cyBwZWFrcyBmb3IgZWFjaCBjaXR5DQoNCmBgYHtyfQ0Kc3RhcnRUaW1lX3Bsb3QgPC0gd2VhdGhlciAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gU3RhcnRUaW1lLCB5ID0gQ2l0eSwgY29sID0gZmN0X2luZnJlcShDaXR5KSkpICsNCiAgICBnZW9tX2ppdHRlcihhbHBoYSA9IDAuMiwgc2l6ZSA9IDAuNSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZSgiU3RhcnRUaW1lIG9mIHRoZSBldmVudHMiKQ0KDQpnZ3Bsb3RseShzdGFydFRpbWVfcGxvdCkNCmBgYA0KYGBge3J9DQojIGh0dHBzOi8vcjRkcy5oYWQuY28ubnovZGF0ZXMtYW5kLXRpbWVzLmh0bWwNCiMgTm90ZSB0aGF0IHdoZW4geW91IHVzZSBkYXRlLXRpbWVzIGluIGEgbnVtZXJpYyBjb250ZXh0IChsaWtlIGluIGEgaGlzdG9ncmFtKSwgMSBtZWFucyAxIHNlY29uZCwgc28gYSBiaW53aWR0aCBvZiA4NjQwMCBtZWFucyBvbmUgZGF5LiBGb3IgZGF0ZXMsIDEgbWVhbnMgMSBkYXkuDQpzdGFydFRpbWVfZnJlcXBsb3QgPC0gd2VhdGhlciAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gU3RhcnRUaW1lLCBjb2wgPSBDaXR5KSkgKw0KICAgIGdlb21fZnJlcXBvbHkoYmlucyA9IDMwKSArICMgYmlud2lkdGggPSA4NjQwMCBzZWNvbmRzID0gMSBkYXksIDYwMCBzID0gMTAgbWludXRlcw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZSgiZnJlcXVlbmN5IHBsb3QgZm9yIFN0YXJ0VGltZSIpICsNCiAgICBmYWNldF9ncmlkKHJvd3MgPSB2YXJzKENpdHkpKQ0KDQpnZ3Bsb3RseShzdGFydFRpbWVfZnJlcXBsb3QpDQpgYGANCmBgYHtyfQ0Kc3RhcnRUaW1lX2JhcnBsb3Rfd2RheSA8LSB3ZWF0aGVyICU+JQ0KICBtdXRhdGUod2RheSA9IHdkYXkoU3RhcnRUaW1lLCBsYWJlbCA9IFRSVUUpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gd2RheSwgZmlsbCA9IENpdHkpKSArDQogICAgZ2VvbV9iYXIoKSArDQogICAgZmFjZXRfZ3JpZChyb3dzID0gdmFycyhDaXR5KSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZSgiZGlzdHJpYnV0aW9uIG92ZXIgd2VlayBkYXlzIikNCiAgDQpnZ3Bsb3RseShzdGFydFRpbWVfYmFycGxvdF93ZGF5KQ0KYGBgDQpgYGB7cn0NCnN0YXJ0VGltZV9iYXJwbG90X3llYXIgPC0gd2VhdGhlciAlPiUNCiAgbXV0YXRlKHllYXIgPSB5ZWFyKFN0YXJ0VGltZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCBmaWxsID0gQ2l0eSkpICsNCiAgICBnZW9tX2JhcigpICsNCiAgICBmYWNldF9ncmlkKHJvd3MgPSB2YXJzKENpdHkpKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKCJkaXN0cmlidXRpb24gb3ZlciB5ZWFycyIpDQogIA0KZ2dwbG90bHkoc3RhcnRUaW1lX2JhcnBsb3RfeWVhcikNCmBgYA0KYGBge3J9DQpzdGFydFRpbWVfYmFycGxvdF9tb250aCA8LSB3ZWF0aGVyICU+JQ0KICBtdXRhdGUobW9udGggPSBtb250aChTdGFydFRpbWUsIGxhYmVsID0gVFJVRSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBtb250aCwgZmlsbCA9IENpdHkpKSArDQogICAgZ2VvbV9iYXIoKSArDQogICAgZmFjZXRfZ3JpZChyb3dzID0gdmFycyhDaXR5KSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZSgiZGlzdHJpYnV0aW9uIG92ZXIgbW9udGhzIikNCiAgDQpnZ3Bsb3RseShzdGFydFRpbWVfYmFycGxvdF9tb250aCkNCmBgYA0KYGBge3J9DQpzdGFydFRpbWVfYmFycGxvdF95ZGF5IDwtIHdlYXRoZXIgJT4lDQogIG11dGF0ZSh5ZGF5ID0geWRheShTdGFydFRpbWUpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geWRheSwgZmlsbCA9IENpdHkpKSArDQogICAgZ2VvbV9iYXIoKSArDQogICAgZmFjZXRfZ3JpZChyb3dzID0gdmFycyhDaXR5KSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZSgiZGlzdHJpYnV0aW9uIG92ZXIgZGF5cyBvZiB5ZWFyIikNCiAgDQpnZ3Bsb3RseShzdGFydFRpbWVfYmFycGxvdF95ZGF5KQ0KYGBgDQpgYGB7cn0NCnN0YXJ0VGltZV9iYXJwbG90X21kYXkgPC0gd2VhdGhlciAlPiUNCiAgbXV0YXRlKG1kYXkgPSBtZGF5KFN0YXJ0VGltZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBtZGF5LCBmaWxsID0gQ2l0eSkpICsNCiAgICBnZW9tX2JhcigpICsNCiAgICBmYWNldF9ncmlkKHJvd3MgPSB2YXJzKENpdHkpKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKCJkaXN0cmlidXRpb24gb3ZlciBkYXlzIG9mIG1vbnRoIikNCiAgDQpnZ3Bsb3RseShzdGFydFRpbWVfYmFycGxvdF9tZGF5KQ0KYGBgDQpgYGB7cn0NCnN0YXJ0VGltZV9iYXJwbG90X2hvdXIgPC0gd2VhdGhlciAlPiUNCiAgbXV0YXRlKGhvdXIgPSBob3VyKFN0YXJ0VGltZSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBob3VyLCBmaWxsID0gQ2l0eSkpICsNCiAgICBnZW9tX2JhcigpICsNCiAgICBmYWNldF9ncmlkKHJvd3MgPSB2YXJzKENpdHkpKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKCJkaXN0cmlidXRpb24gb3ZlciBob3VycyIpDQogIA0KZ2dwbG90bHkoc3RhcnRUaW1lX2JhcnBsb3RfaG91cikNCmBgYA0KYGBge3J9DQpzdGFydFRpbWVfYmFycGxvdF9taW51dGUgPC0gd2VhdGhlciAlPiUNCiAgbXV0YXRlKG1pbnV0ZSA9IG1pbnV0ZShTdGFydFRpbWUpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gbWludXRlLCBmaWxsID0gQ2l0eSkpICsNCiAgICBnZW9tX2JhcigpICsNCiAgICBmYWNldF9ncmlkKHJvd3MgPSB2YXJzKENpdHkpKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKCJkaXN0cmlidXRpb24gb3ZlciBtaW51dGVzIikNCiAgDQpnZ3Bsb3RseShzdGFydFRpbWVfYmFycGxvdF9taW51dGUpDQpgYGANCmBgYHtyfQ0KIyBTZXR0aW5nIGxhcmdlciBjb21wb25lbnRzIG9mIGEgZGF0ZSB0byBhIGNvbnN0YW50IGlzIGEgcG93ZXJmdWwgdGVjaG5pcXVlIHRoYXQgYWxsb3dzIHlvdSB0byBleHBsb3JlIHBhdHRlcm5zIGluIHRoZSBzbWFsbGVyIGNvbXBvbmVudHMuDQpzdGFydFRpbWVfY291bnQgPC0gd2VhdGhlciAlPiUNCiAgbXV0YXRlKHN0YXJ0X2hvdXIgPSB1cGRhdGUoU3RhcnRUaW1lLCBtZGF5ID0gMSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBzdGFydF9ob3VyLCBjb2wgPSBDaXR5KSkgKw0KICAgIGdlb21fZnJlcXBvbHkoKSArDQogICAgZmFjZXRfZ3JpZChyb3dzID0gdmFycyhDaXR5KSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgZ2d0aXRsZSgibm90IHNlZWluZyB0aGUgdXNlIGhlcmUsIGJ1dCB3YW50ZWQgdG8gY2hlY2sgb3V0IikNCg0KZ2dwbG90bHkoc3RhcnRUaW1lX2NvdW50KQ0KYGBgDQoNCi0tLQ0KdW5pdmFyaWF0ZSBEdXJhdGlvbg0KLS0tDQpzaW5jZSBodW1hbiBqdWRnbWVudCBzZWVtcyB0byBiZSBpbnZvbHZlZCwgdGhlIGR1cmF0aW9uIGhhcyBwZWFrcyBhdCB0aGUgZnVsbCBob3VycywgeW91IGV2ZW4gY2FuIHNlZSB0aGUgZGlwcyBpbiB0aGUgcG9pc3NvbiBsaWtlIGRpc3RyaWJ1dGlvbg0KZHVyYXRpb24gc3RhdHM6IFNlYXR0bGUgbWVkaWFuIDYwIG1pbiwgcTMgMTIwIG1pbjsgTmV3IFlvcmsgbWVkaWFuIDQ3IG1pbiBxMyA3MiBtaW47IExvcyBBbmdlbGVzIG1lZGlhbiA2MCBtaW4gcTMgMTIwIG1pbiwgSG91c3RvbiBtZWRpYW4gNjAgbWluIHEzIDk4IG1pbjsgTG9zIEFuZ2VsZXMgYW5kIFNlYXR0bGUgc2VlbSBzaW1pbGFyIGluIGRpc3RyaWJ1dGlvbg0KDQpgYGB7cn0NCmR1cmF0aW9uX2hpc3RwbG90X2FsbCA8LSB3ZWF0aGVyICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBEdXJhdGlvbiwgZmlsbCA9IGZjdF9pbmZyZXEoQ2l0eSkpKSArDQogICAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKCJEdXJhdGlvbiBvZiB0aGUgZXZlbnRzIikNCg0KZ2dwbG90bHkoZHVyYXRpb25faGlzdHBsb3RfYWxsKQ0KYGBgDQpgYGB7cn0NCmR1cmF0aW9uX2hpc3RwbG90IDwtIHdlYXRoZXIgJT4lDQogIGdncGxvdChhZXMoeCA9IER1cmF0aW9uLCBmaWxsID0gZmN0X2luZnJlcShDaXR5KSkpICsNCiAgICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDMwKSArDQogICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICBnZ3RpdGxlKCJEdXJhdGlvbiBvZiB0aGUgZXZlbnRzIikgKw0KICAgIGZhY2V0X2dyaWQocm93cyA9IHZhcnMoQ2l0eSkpDQoNCmdncGxvdGx5KGR1cmF0aW9uX2hpc3RwbG90KQ0KYGBgDQpgYGB7cn0NCmR1cmF0aW9uX2JveHBsb3QgPC0gd2VhdGhlciAlPiUNCiAgZ2dwbG90KGFlcyh5ID0gYXMubnVtZXJpYyhEdXJhdGlvbiksIHggPSBDaXR5LCBjb2wgPSBmY3RfaW5mcmVxKENpdHkpKSkgKw0KICAgIGdlb21fYm94cGxvdCgpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgZ2d0aXRsZSgiRHVyYXRpb24gb2YgdGhlIGV2ZW50cyIpDQoNCmdncGxvdGx5KGR1cmF0aW9uX2JveHBsb3QpDQpgYGANCg0KYGBge3J9DQpkdXJhdGlvbl9wb2ludCA8LSB3ZWF0aGVyICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBhcy5udW1lcmljKER1cmF0aW9uKSwgeSA9IENpdHksIGNvbCA9IGZjdF9pbmZyZXEoQ2l0eSkpKSArDQogICAgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjIsIHNpemUgPSAwLjUpICsNCiAgICB0aGVtZV9taW5pbWFsKCkgKw0KICAgIGdndGl0bGUoIkR1cmF0aW9uIG9mIHRoZSBldmVudHMiKQ0KDQpnZ3Bsb3RseShkdXJhdGlvbl9wb2ludCkNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoZGxvb2tyKQ0KDQp3ZWF0aGVyICU+JSANCiAgbXV0YXRlKER1cmF0aW9uID0gYXMubnVtZXJpYyhEdXJhdGlvbikpICU+JQ0KICBwbG90X25vcm1hbGl0eShEdXJhdGlvbikNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=